
// #define DEBUG

#include "WavePlotInterface.h"

WavePlotInterface::WavePlotInterface(QCustomPlot *wavePlot, uint8_t channalNum,
                                        double ratio, double offset, double timeScale):
    wavePlot(wavePlot)
    // eegData_voltage(channalNum)
{
    #ifdef DEBUG
    std::cout << "WavePlotInterface DEBUG ON..." << std::endl;
    #endif // DEBUG

    amplitudeRatio = ratio;
    amplitudeOffset = offset;
    this->timeScale = timeScale;

    // m_countGraph = eegData_voltage.channalNum;
    m_countGraph = channalNum;
    pointNumPerLine = 3000;
    plot_index = 0;
    flag_wavePlotting = false;
    // eegData_voltage.data.reserve(1000000);
    // 分配出m_countGraph导的空间
    xValVec.resize(max_points);
    yValVec.resize(m_countGraph);
    for (int i = 0; i < m_countGraph; ++i) {
        yValVec[i].resize(max_points);  // 为每条曲线的 y 值分配 10000 个点
    }

    plotInit();
    begin_plot();
}

WavePlotInterface::~WavePlotInterface(){    
    timer_rePlot.stop();
    timer_addData.stop();
}

/**********************************
 * 函数名：plotInit
 * 功能：画图窗口初始化
 * 输入：无
 * 输出：无
 * 备注：无
**********************************/
int WavePlotInterface::plotInit(){
    // 隐藏y轴刻度值
    // wavePlot->yAxis->setTickLabels(false); 
    // 设置y轴范围
    // wavePlot->yAxis->setRange(-150, -110);
    wavePlot->yAxis->setRange(2200, 3500);
    // QSharedPointer<QCPAxisTicker> ticker(new QCPAxisTicker);
    // ticker->setTickCount(200); // 刻度间距为2
    // wavePlot->yAxis->setTicker(ticker);
    // 窗口刷新
    connect(&timer_rePlot, SIGNAL(timeout()), this, SLOT(timeToRePlot()));
    // 添加数据
    // connect(&dataTimer_wave, SIGNAL(timeout()), this, SLOT(add_randomData()));
    // connect(&timer_addData, SIGNAL(timeout()), this, SLOT(addData()));
    // wavePlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);
    wavePlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);

    // 透明
    wavePlot->setBackground(Qt::transparent);
    wavePlot->setStyleSheet("background: transparent;");

    // m_start_wave = false;

    return 0;
}

/**********************************
 * 函数名：begin_plot
 * 功能：
 * 输入：无
 * 输出：无
 * 备注：无
**********************************/
void WavePlotInterface::begin_plot(){
    // eegData_voltage.clear();
    plot_index = 0;

    wavePlot->clearGraphs();//清除所有graph
    QPen pen;
    pen.setWidth(2);
    wavePlot->setOpenGl(true);  // 启用 OpenGL
    if (wavePlot->openGl()) {
        // qDebug() << "OpenGL is enabled.";
    } else {
        qDebug() << "OpenGL is not enabled.";
    }
    //添加曲线
    for(int i=0; i<m_countGraph; ++i)
    {
        wavePlot->addGraph();
        //颜色随机
        pen.setColor(QColor(qrand()%100+50,qrand()%100+50,qrand()%100+50));
        wavePlot->graph(i)->setPen(pen);//
    }
    //设置y轴范围
    // wavePlot->yAxis->setRange(-1, m_countGraph*2);
    //设置x轴范围
    // int size = ui->spinBox2->value();
    int size = pointNumPerLine;
    wavePlot->xAxis->setRange(0, size, Qt::AlignRight);
    //定时添加和刷新数据
    timer_rePlot.start(10); // 间隔16ms刷新一次
    timer_addData.start(5); // 间隔时间5ms添加一次数据
    flag_wavePlotting = true;
    // ui->btn_start2->setText("停止");
    // static int count = 0;
    // printf("In WavePlotInterface::begin_plot, count=%d\n",++count);
    
}

/**********************************
 * 函数名：add_eegData
 * 功能：向plot对象增加数据点
 * 输入：无
 * 输出：无
 * 备注：无
**********************************/
void WavePlotInterface::addData(const GenEEGData& inputData){

    // auto BT = std::chrono::steady_clock::now();
    if(inputData.dataHead.channalNum != m_countGraph){
        std::cerr << "In WavePlotInterface, data receive error!" << std::endl;
        return;
    }
    // int new_pointNum = eegData_voltage.data.size() - plot_index;
    int new_pointNum = inputData.data.size();  // 新数据点数
    // int total_points = plot_index + new_pointNum;  // 总的点数
    // int excess_points = total_points - max_points;      // 超出后的点数

    // // 如果总的点数超过了 max_points，移除前面的点
    // if (total_points > max_points) {
    //     std::cout << "over" << std::endl;
    //     // std::memmove(xValVec.data(), xValVec.data() + excess_points, (max_points-excess_points)*sizeof(double));
    //     // for (int waveId = 0; waveId < m_countGraph; ++waveId) {
    //     //     yValVec[waveId].remove(0, excess_points);  // 每条曲线移除前面多余的 y 坐标
    //     // }
    //     for(int count=0; count < new_pointNum; ++count){
    //         // x轴数据填充
    //         xValVec[max_points - new_pointNum + count] = plot_index + count;
    //         // y轴数据填充
    //         for(int waveId = 0; waveId < m_countGraph; ++waveId){
    //             yValVec[waveId][max_points - new_pointNum + count] = 
    //                 inputData.data.at(count).at(waveId) / amplitudeRatio + amplitudeOffset * m_countGraph;
    //         }
    //     }
    // }
    // else{
    //     for(int count=0; count < new_pointNum; ++count){
    //         // x轴数据填充
    //         xValVec[plot_index + count] = plot_index + count;
    //         // y轴数据填充
    //         for(int waveId = 0; waveId < m_countGraph; ++waveId){
    //             yValVec[waveId][plot_index + count] = 
    //                 inputData.data.at(count).at(waveId) / amplitudeRatio + amplitudeOffset * m_countGraph;
    //         }
    //     }
    // }

    // for(int waveId = 0; waveId < m_countGraph; ++waveId){
    //         wavePlot->graph(waveId)->setData(xValVec, yValVec[waveId]);
    // }

    // // std::cout << "yValVec.size()=" << yValVec.size() << std::endl;
    // for (int waveId = 0; waveId < m_countGraph; ++waveId) {
    //     for (int pointCount = 0; pointCount < new_pointNum; ++pointCount) {
    //         // y[j] = eegData_voltage.data.at(j + plot_index).at(i) / amplitudeRatio + amplitudeOffset * i; // y 轴坐标
    //         // yValVec.append(inputData.data.at(new_pointNum).at(m_countGraph) / amplitudeRatio + amplitudeOffset * m_countGraph);
    //         // std::cout << "m_countGraph=" << m_countGraph << std::endl;
    //         // std::cout << "yValVec.size=" << yValVec.size() << std::endl;

    //         yValVec[waveId].append(2.35);
    //         // std::cout << "yValVec[waveId].size()=" << yValVec[waveId].size() << std::endl;
    //     }
    //     wavePlot->graph(waveId)->setData(xValVec, yValVec[waveId]);
    // }

    // 优化添加数据方式，避免多次调用addData影响性能
    #if 1
    QVector<double> x(new_pointNum);
    for (int j = 0; j < new_pointNum; ++j) {
        x[j] = plot_index + j; // x 轴坐标
    }
    // 添加新数据
    for (int i = 0; i < wavePlot->graphCount(); ++i) {
        QVector<double> y(new_pointNum);
        for (int j = 0; j < new_pointNum; ++j) {
            y[j] = inputData.data.at(j).at(i) / amplitudeRatio + amplitudeOffset * i; // y 轴坐标
        }
        wavePlot->graph(i)->addData(x, y);
        // 优化：保持最多 10000 个点
        // int current_data_size = wavePlot->graph(i)->data()->size(); // current_data_size = wavePlot->graph(i)->dataCount()+1
        // if (current_data_size > max_points) {
        //     // wavePlot->graph(i)->removeData(current_data_size - max_points); // 移除前面的数据，保持最新的 10000 个点
        //     std::cout << "before delete:" << wavePlot->graph(i)->data()->size() << std::endl;
        //     // wavePlot->graph(i)->data()->remove(0, wavePlot->graph(i)->dataCount() - max_points);
        //     wavePlot->graph(i)->data()->clear();
        //     std::cout << "after delete:" << wavePlot->graph(i)->data()->size() << std::endl;
        //     std::cout << "delete Data" << std::endl;
        // }
    }
    #else
    for(int i=0; i<wavePlot->graphCount(); ++i)
    {
        for(int j=0; j<new_pointNum; ++j)
        {
            wavePlot->graph(i)->addData(wavePlot->graph(i)->dataCount(), 
                                            eegData_voltage.data.at(j+plot_index).at(i)/amplitudeRatio + amplitudeOffset*i);
            // std::cout << "eegData_voltage:" << eegData_voltage.at(j+plot_index).data[25] << std::endl;
        }
    }
    #endif

    plot_index += new_pointNum;
    // std::cout << "size:" << wavePlot->graph(0)->data()->size() << std::endl;

    // auto AT = std::chrono::steady_clock::now();
    // double duration_millsecond = std::chrono::duration<double, std::milli>(AT - BT).count();
    // std::cout << "addData_times:" << duration_millsecond << "ms" << std::endl;
}

void WavePlotInterface::plotDataUpdate(const GenEEGData& data){
    // eegData_voltage.inserData(data);

    addData(data);
    std::cout << "finish insert" << std::endl;
}

/**********************************
 * 函数名：timeToRePlot
 * 功能：刷新
 * 输入：无
 * 输出：无
 * 备注：无
**********************************/ 
void WavePlotInterface::timeToRePlot()
{
    static QTime time(QTime::currentTime());
    double key = time.elapsed()/1000.0; // time elapsed since start of demo, in seconds
    // 每次刷新pointNumPerLine个点,右对齐
    // wavePlot->xAxis->setRange(wavePlot->graph(2)->dataCount(), pointNumPerLine, Qt::AlignRight);
    wavePlot->xAxis->setRange(wavePlot->graph(2)->dataCount(), timeScale, Qt::AlignRight);
    
    // QEventLoop loop;//定义一个新的事件循环
    // QTimer::singleShot(1000, &loop, SLOT(quit()));//创建单次定时器，槽函数为事件循环的退出函数
    // loop.exec();//事件循环开始执行，程序会卡在这里，直到定时时间到，本循环被退出
    //重绘
    wavePlot->replot(QCustomPlot::rpQueuedReplot);
    //wavePlot->replot();
    #ifdef DEBUG
    static double lastFpsKey;
    static int frameCount;
    ++frameCount;
    if (key-lastFpsKey > 1) // 每1s求一次值
    {
        float frame = frameCount / (key-lastFpsKey);
        lastFpsKey = key;
        frameCount = 0;
        std::cout << "FPS: " << frame << std::endl; // 打印FPS
    }
    #endif
}

/**********************************
 * 函数名：stopPlot
 * 功能：停止画图
 * 输入：无
 * 输出：无
 * 备注：注意只是显示停止，采集还在继续，
 *      等下次开始画图的时候，累积的数据会一起画出来
**********************************/
void WavePlotInterface::stopPlot(){
    flag_wavePlotting = false;
    // timer_addData.stop();
    timer_rePlot.stop();
}

void WavePlotInterface::clearAll(){
    for (int i = 0; i < wavePlot->graphCount(); ++i) {
        wavePlot->graph(i)->data()->clear();
    }
    wavePlot->replot(QCustomPlot::rpQueuedReplot);
    plot_index = 0;
    // std::cout << "size:" << wavePlot->graph(0)->data()->size() << std::endl;
}



void WavePlotInterface::amplitudeRatioUpdate(double ratio){
    amplitudeRatio = ratio;
}
void WavePlotInterface::amplitudeOffsetUpdate(double offset){
    amplitudeOffset = offset;
}
void WavePlotInterface::timeScaleUpdate(double scale){
    timeScale = scale;
}
